/*
 * tlistaporo.cpp
 *
 *  Created on: 09/12/2009
 *      Author: javier
 */
#include "tlistaporo.h"
#include "tporo.h"

TListaNodo::TListaNodo()
{
	anterior = NULL;
	siguiente = NULL;
}

TListaNodo::TListaNodo( const TListaNodo &n)
{
	if ( this != &n)
	{
		e = n.e;
		siguiente = n.siguiente;
		anterior = n.anterior;
	}
}

TListaNodo::~TListaNodo()
{
	e.~TPoro();
	anterior = NULL;
	siguiente = NULL;
}

TListaNodo&
TListaNodo::operator =(const TListaNodo &n)
{
	e = n.e;

	siguiente = n.siguiente;
	anterior = n.anterior;

	return *this;
}

////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////

TListaPosicion::TListaPosicion()
{
	pos = NULL;
}

TListaPosicion::TListaPosicion( const TListaPosicion &p )
{
	if( p.pos != NULL)
	{
		pos = new TListaNodo(*p.pos);
	}
}

TListaPosicion::~TListaPosicion()
{
	if( pos != NULL )
	{
		pos = NULL;
	}
}

TListaPosicion&
TListaPosicion::operator =( const TListaPosicion &p)
{
	if( this != &p)
	{
		if( p.pos != NULL)
		{
			this->~TListaPosicion();
			pos = p.pos;
		}
		else
		{
			this->~TListaPosicion();
		}
	}

	return *this;
}

bool
TListaPosicion::operator ==(const TListaPosicion &p)
{
	bool igual = false;

	if ( &pos == &p.pos)
	{
		igual = true;
	}

	return igual;
}

TListaPosicion
TListaPosicion::Anterior() const
{
	TListaPosicion aux;

	if( pos->anterior !=NULL)
		aux.pos = pos->anterior;

	return aux;
}

TListaPosicion
TListaPosicion::Siguiente() const
{
	TListaPosicion aux;

	if( pos->siguiente !=NULL)
		aux.pos = pos->siguiente;

	return aux;
}

bool
TListaPosicion::EsVacia() const
{
	if( pos == NULL)
		return true;

	else return false;
}

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////


TListaPoro::TListaPoro()
{
	primero = NULL;
	ultimo = NULL;
}

TListaPoro::TListaPoro( const TListaPoro &p )
{
	if( this != &p)
	{

		primero = new TListaNodo(*p.primero);
		TListaPosicion ant;
		ant.pos = p.primero;
		TListaPosicion sig;
		sig.pos = p.primero;
		sig.pos = sig.pos->siguiente;

		//if( p.primero->siguiente != NULL )
		if( sig.pos != NULL )
		{
			//TListaNodo *ant = p.primero;
			//TListaNodo *sig = p.primero->siguiente;
			while(  sig.pos != NULL )
			{
				ant.pos->siguiente = new TListaNodo(*sig.pos);
				ant.pos = sig.pos;
				sig.pos = sig.pos->siguiente;
				if( sig.pos == NULL ) ultimo = ant.pos;
			}
			ant.pos = NULL;
			sig.pos = NULL;
		}
	}
}

TListaPoro::~TListaPoro()
{
	if ( primero != NULL)
	{
		TListaNodo *ant = primero;
		if ( primero->siguiente != NULL )
		{
			TListaNodo *sig = primero->siguiente;
			while( sig != NULL )
			{
				delete ant;
				ant = sig;
				sig = sig->siguiente;
			}
			sig = NULL;
		}
		else
		{
			delete ant;
		}
		ant = NULL;
		primero = NULL;
		ultimo = NULL;
	}

}

TListaPoro &
TListaPoro::operator =( const TListaPoro &p)
{

	if( this != &p)
	{
		TListaPosicion ant;
		TListaPosicion sig;
		TListaPosicion antp;
		TListaPosicion sigp;

		this->~TListaPoro();

		ant.pos = p.primero;

		while( ant.pos != NULL )
		{
				this->Insertar(ant.pos->e);
				ant.pos = ant.pos->siguiente;
		}
		//primero = new TListaNodo(*p.primero);
		/*
		this->~TListaPoro();
		antp.pos = p.primero;

		if( antp.pos != NULL)
		{
			TListaNodo *nodo = new TListaNodo;
			nodo->e = antp.pos->e;
			primero = nodo;
			ant.pos = primero;
			//sig.pos = ant.pos->siguiente;

			sigp.pos = antp.pos->siguiente;

			//if( p.primero->siguiente != NULL )
			if( antp.pos->siguiente != NULL )
			{
				//TListaNodo *ant = p.primero;
				//TListaNodo *sig = p.primero->siguiente;
				while(  sigp.pos->NULL != NULL )
				{
					TListaNodo *nodo2 = new TListaNodo;
					nodo2->e = sigp.pos->e;

					antp.pos = sigp.pos;
					sigp.pos = sigp.pos->siguiente;
					if( sigp.pos == NULL ) ultimo = antp.pos;
				}
				ant.pos = NULL;
				sig.pos = NULL;
			}
			else
			{
				ultimo = primero;
			}
		}*/

	}

	return *this;
}

bool
TListaPoro::operator ==(const TListaPoro &p) const
{
	TListaNodo *aux1 = primero;
	TListaNodo *aux2 = p.primero;
	bool igual = true;

	if( aux1 != NULL && aux2 != NULL)
	{

	}
	else
	{
		if( !(aux1 == NULL && aux2 == NULL) ) igual = false;
	}


	return igual;
}


TListaPoro
TListaPoro::operator +( const TListaPoro &l)
{
	TListaPoro aux;



	if( this->primero != NULL && l.primero != NULL)
	{
		// Ir metiendo Tnodos en la lista aux de forma que se ordenen.
		// por ejemplo metemos la primera lista y los otros los ordenamos...
		aux = *this;
		TListaPosicion recorre;
		recorre.pos = l.primero;

		while( recorre.pos != NULL )
		{
			aux.Insertar( recorre.pos->e );
		}
	}
	else
	{
		if( this == NULL)
		{
			aux = l;
		}
		else
		{
			aux = *this;
		}
	}

	return aux;
}

TListaPoro
TListaPoro::operator -( const TListaPoro &l)
{
	TListaPoro aux;
	TListaPosicion insertar;
	insertar.pos = primero;

	if( !l.EsVacia() )
	{
		if( insertar.pos != NULL )
		{
			if( !(*this == l) )
			{
				while( insertar.pos != NULL )
				{

					if( !(l.Buscar( insertar.pos->e )) )
					{
						aux.Insertar( insertar.pos->e );
					}

					insertar.pos = insertar.pos->siguiente;
				}
			}
		}
	}
	else aux = *this;

	return aux;

}

bool
TListaPoro::EsVacia() const
{
	bool esvacia = false;

	if( primero == NULL && ultimo == NULL )
	{
		esvacia = true;
	}

	return esvacia;
}


bool
TListaPoro::Insertar( const TPoro &p)
{
 // Insertar el poro en la lista de forma ordenada
 // de menor a mayor.
	TListaPosicion ant;
	TListaPosicion sig;
	bool insertado = false;

	//cout << "Se va a insertar el poro: " << p << endl;

	ant.pos = primero;
	//sig.pos = ant.pos->siguiente;

	if( !this->Buscar(p) )
	{

		if( !this->EsVacia() )
		{
			if( p.Volumen() < ant.pos->e.Volumen() )
			{
				TListaNodo *nodo = new TListaNodo;
				nodo->e = p;
				nodo->siguiente = ant.pos;
				nodo->anterior = NULL;
				ant.pos->anterior = nodo;
				primero = nodo;
				insertado = true;
			}
			else // si son iguales.
			{
				if( p.Volumen() == ant.pos->e.Volumen() )
				{

					TListaNodo *nodo = new TListaNodo;
					nodo->e = p;

					if( ant.pos->siguiente != NULL)
					{
						sig.pos = ant.pos->siguiente;
						sig.pos->anterior = nodo;
						ant.pos->siguiente = nodo;

						nodo->siguiente = sig.pos;
						nodo->anterior = ant.pos;
					}
					else
					{
						ant.pos->siguiente = nodo;
						nodo->anterior = ant.pos;
						nodo->siguiente = NULL;
						ultimo = nodo;
					}

					insertado = true;
				}
			}

			while( insertado == false ) // posicion intermedia
			{
				//if( ant.pos->siguiente != NULL )
				if( ant.pos != NULL )
				{
					//sig.pos = ant.pos->siguiente;

					//if( sig.pos != NULL )
					if( ant.pos->siguiente != NULL )
					{
						sig.pos =ant.pos->siguiente;

						if( p.Volumen() < sig.pos->e.Volumen() ) // por enmedio
						{
							TListaNodo *nodo = new TListaNodo;
							nodo->e = p;
							nodo->anterior = ant.pos;
							ant.pos->siguiente = nodo;
							nodo->siguiente = sig.pos;
							sig.pos->anterior = nodo;
							insertado = true;
						}
						else
						{  // comprobar si son iguales los poros;
							if( p.Volumen() == ant.pos->e.Volumen() )
							{

								TListaNodo *nodo = new TListaNodo;
								sig.pos->anterior = nodo;
								ant.pos->siguiente = nodo;
								nodo->e = p;
								nodo->siguiente = sig.pos;
								nodo->anterior = ant.pos;

							}
						}
					}
					else
					{	//Insercion al final
						TListaNodo *nodo = new TListaNodo;
						nodo->e = p;
						nodo->anterior = ant.pos;
						nodo->siguiente = NULL;
						ant.pos->siguiente = nodo;
						ultimo = nodo;
						insertado = true;
					}
				}

				//iterar punteros si no se cumplen los ifs
				ant.pos = ant.pos->siguiente;
				//ant.pos->siguiente = sig.pos;
				//sig.pos = sig.pos->siguiente;

			}// Fin del while


		}
		else
		{
			// Es vacia
			TListaNodo *nodo = new TListaNodo;
			nodo->e = p;
			nodo->anterior = NULL;
			nodo->siguiente = NULL;
			primero = nodo;
			ultimo = nodo;
			insertado = true;
		}
	}
	ant.pos = NULL;
	sig.pos = NULL;

	return insertado;
}


bool
TListaPoro::Borrar(const TPoro &p)
{
	bool borra = false;

	if( this->Buscar(p) )
	{
		TListaPosicion sig, ant, auxborrado;
		sig.pos = primero;

		while( !borra )
		{
			if( sig.pos->e == p )
			{
				borra = true;

				if( sig.pos->siguiente == NULL)
				{
					if(ant.pos!=NULL) //ultimo, alguien
					{
						ant.pos->siguiente=NULL;
						delete sig.pos;
						ultimo = ant.pos;
					}
					else //ultimo sol
					{
						delete sig.pos;
						primero=NULL;
						ultimo=NULL;
					}
				}
				else if(ant.pos!=NULL)
				{
					//enmedio
					ant.pos->siguiente=sig.pos->siguiente;
					auxborrado.pos = sig.pos;
					sig.pos = sig.pos->siguiente;
					sig.pos->anterior = ant.pos;
					delete auxborrado.pos;
				}
				else { //primero
					auxborrado.pos = sig.pos;
					sig.pos = sig.pos->siguiente;
					sig.pos->anterior = NULL;
					delete auxborrado.pos;
					primero = sig.pos;
				}
			}
			else {
				ant.pos=sig.pos;
				sig.pos=sig.pos->siguiente;
			}
		}


		/*
		while( sig.pos!=NULL &&  borra != true )
		{
			if( sig.pos->e == p)
			{
				ant.pos->siguiente = sig.pos->siguiente;
				auxborrado.pos = sig.pos;
				sig.pos = sig.pos->siguiente;
				delete auxborrado.pos;
				sig.pos->anterior = ant.pos;
				borra = true;
			}
			ant.pos = sig.pos;
			sig.pos = sig.pos->siguiente;
		}
		ant.pos = NULL;
		sig.pos = NULL;
		auxborrado.pos = NULL;*/
	}

	return borra;
}


bool
TListaPoro::Borrar( const TListaPosicion &p)
{
	bool borra = false;

	if( p.pos != NULL )
	{
		TListaPosicion ant,sig;
		ant.pos = p.pos->anterior;
		sig.pos = p.pos->siguiente;

		ant.pos->siguiente = sig.pos;
		sig.pos->anterior = ant.pos;
		delete p.pos;
		borra = true;
	}

	return borra;
}

TPoro
TListaPoro::Obtener(const TListaPosicion &p)
{
	TPoro aux;

	if( p.pos != NULL)
	{
		aux =  p.pos->e;
	}

	return aux;
}

bool
TListaPoro::Buscar( const TPoro &p) const
{
	bool encontrado = false;
	TListaPosicion position;
	position.pos = this->primero;

	while( position.pos != NULL && !encontrado )
	{
		if( position.pos->e == p )
		{
			encontrado = true;
		}
		else
		{
			position.pos = position.pos->siguiente;
		}
	}

	return encontrado;
}


int
TListaPoro::Longitud()
{
	int lon = 0;
	TListaPosicion aux;
	aux.pos = primero;

	while( aux.pos != NULL )
	{
		lon++;
		aux.pos = aux.pos->siguiente;
	}

	return lon;
}

TListaPosicion
TListaPoro::Primera()
{
	TListaPosicion aux;

	if( !this->EsVacia() )
	{
		aux.pos = primero;
	}

	return aux;
}

TListaPosicion
TListaPoro::Ultima()
{
	TListaPosicion aux;

	if( !this->EsVacia() )
	{
		aux.pos = ultimo;
	}

	return aux;
}

ostream &
operator<<(ostream &os, const TListaPoro &l)
{
	if( !l.EsVacia() )
	{
		TListaPosicion aux;
		aux.pos = l.primero;

		os << "(" << aux.pos->e;
		aux.pos = aux.pos->siguiente;

		while( aux.pos != NULL )
		{
			os << " " << aux.pos->e;
			aux.pos = aux.pos->siguiente;
		}
		os << ")";
		aux.pos = NULL;
	}
	else
	{
		os << "()";
	}

	return os;
}
